package handler

import (
	"context"
	"encoding/json"
	"qld2devservice/models"
	dev "qld2devservice/proto"
	"qld2devservice/service"
	"qld2devservice/utils"
	"strconv"
	"time"
)

// apiController 控制器
type handlerDevController struct{}

func NewDevController() dev.DevServer {
	return &handlerDevController{}
}

// OutLetOpen 打开设备
func (that *handlerDevController) OutLetOpen(ctx context.Context, p *dev.OutLetOpenRequest) (res *dev.OutLetOpenResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetOpen request", utils.TransProtoToJson(p))
	res = &dev.OutLetOpenResponse{}
	//删除功率List  设置平均功率为 -1 _start
	if err := service.RedisDelNoHeader("/qld2pricecalculationservice/" + p.SnNum + "/ListPower"); err != nil {

		return res, utils.WrapError(err, "redis删除功率List失败")
	}
	err = service.RedisSaveNoHeader("/qld2pricecalculationservice/"+p.SnNum+"/averagePower", "-1")
	if err != nil {

		return res, utils.WrapError(err, "redis设置平均功率为-1失败")
	}

	if err := service.RedisDelNoHeader("/qld2devservice/" + p.SnNum + "/listLowFullPower"); err != nil {

		return res, utils.WrapError(err, "redis删除功率List失败")
	}
	if err := service.RedisDelNoHeader("/qld2devservice/" + p.SnNum + "/startLowFullTime"); err != nil {

		return res, utils.WrapError(err, "redis删除功率startLowFullTime失败")
	}

	//删除功率List  设置平均功率为 -1 _end

	if err = service.RedisSave(p.SnNum+"/operateFlag", ""); err != nil {
		return res, utils.WrapError(err, "OutLetOpen: redis保存operateFlag失败")
	}
	defer func() {
		//fmt.Println("defer里面的响应信息:", res)
		if res.OpenFlag > 0 || res.TimeOut {
			if err1 := models.SetQldOutletValue(p.SnNum, 0, 0); err1 != nil {
				utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err1, "OutLetOpen: 0，更新数据库失败"))
			}
		} else {
			orderSn := p.OrderSn
			time.AfterFunc(5*time.Second, func() {
				b, err2 := json.Marshal(map[string]interface{}{
					"orderSn": orderSn,
					"retCode": 200,
				})
				if err2 != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err2, "OutLetOpen:json字符串转换获取失败"))
				}
				if err2 = service.MqttNoticeSend(p.SnNum+"/orderCreate", string(b)); err2 != nil {
					utils.MyPrint(utils.PRINT_ERROR, err2.Error())
				}
			})
		}
		if res.OpenFlag > 0 && len(res.OpenMsg) == 0 {
			res.OpenMsg = "设备应答异常"
		}
		if err2 := service.RedisDel(p.SnNum + "/operateFlag"); err2 != nil {
			utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err2, "OutLetOpen: redis删除operateFlag失败"))
		}
		if err != nil {
			service.PutErrorMsg("OutLetOpen"+err.Error(), p.SnNum, service.UserControlErr)
			utils.MyPrint(utils.PRINT_ERROR, err.Error())
			err = nil
			res.OpenFlag = 1
			res.OpenMsg = "操作错误"
		}
		utils.MyPrint(utils.PRINT_INFO, "OutLetOpen response", utils.TransProtoToJson(res))
	}()

	if qldOutlets, err2 := models.GetQldOutletsBySnNum(p.SnNum); err2 != nil {
		return res, utils.WrapError(err2, "OutLetOpen: 1，获取数据设备信息失败")
	} else if len(qldOutlets) == 0 {
		res.OpenMsg = "设备不存在"
		return res, nil
	} else {
		res.OpenMsg = service.CheckEmergencyStop(p.SnNum, qldOutlets[0].Type)
		if len(res.OpenMsg) > 0 {
			res.OpenFlag = 1
			return res, nil
		}
		//获取的设备号对应的园区id存入redis
		if err = service.RedisSave(p.SnNum+"/areaId", strconv.FormatInt(qldOutlets[0].AreaId, 10)); err != nil {
			return res, utils.WrapError(err, "OutLetOpen: 13，redis保存设备园区id失败")
		}

		//fmt.Println("获取桩的类型", qldOutlets[0].Type)
		if qldOutlets[0].Type == 6 || qldOutlets[0].Type == 10 || qldOutlets[0].Type == 12 || qldOutlets[0].Type == 13 {
			res.TimeOut, res.OpenFlag, res.OpenMsg, err = service.DeviceOpen(p.UserID, p.SnNum, p.OrderSn, p.Amount, p.Balance, p.OpenType, p.TimeType, p.Hour)
			//fmt.Println("正常返回信息:", res)
		} else if qldOutlets[0].Type == 8 {
			res.TimeOut, res.OpenFlag, res.OpenMsg, err = service.StartChargingSpw(p.UserID, p.SnNum, p.OrderSn, p.Amount, p.Balance)
		} else {
			priceId := qldOutlets[0].PriceId
			//判断园区是否是专用园区
			if qldArea, err3 := models.GetAreaById(qldOutlets[0].AreaId); err3 != nil {
				return res, utils.WrapError(err2, "OutLetOpen: 10，获取园区信息失败")
			} else {
				//专用园区
				if qldArea.Private == 3 && qldOutlets[0].Type == 5 {
					//判断用户是否有权限操作该设备
					inArea, err := models.JudgeUserInArea(p.UserID, qldOutlets[0].AreaId)
					if err != nil {
						return res, utils.WrapError(err2, "OutLetOpen: 10，获取权限失败")
					}

					if inArea && qldOutlets[0].PriceInnerId > 0 {
						priceId = qldOutlets[0].PriceInnerId
					}
				}
			}
			utils.MyPrint(utils.PRINT_INFO, "设备开启获取的价格策略Id：", priceId)
			//if qldAmountPrice, err2 := models.GetQldAmountPriceById(qldOutlets[0].PriceId); err2 != nil {
			if qldAmountPrice, err2 := models.GetQldAmountPriceById(priceId); err2 != nil {
				return res, utils.WrapError(err2, "OutLetOpen: 11，获取设备价格失败")
			} else {
				if err = service.RedisSave(p.SnNum+"/price", qldAmountPrice.PriceStr); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 13，redis保存设备价格失败")
				}
			}
			if p.TimeType == 2 {
				if qldOutletControl, err2 := models.GetQldOutletControlById(p.ControlId); err2 != nil {
					return res, utils.WrapError(err2, "OutLetOpen: 11，获取设备价格失败")
				} else {
					if err = service.RedisSave(p.SnNum+"/control", qldOutletControl.ControlStr); err != nil {
						return res, utils.WrapError(err, "OutLetOpen: 13，redis保存设备价格失败")
					}
					if err = service.RedisSave(p.SnNum+"/controlName", qldOutletControl.Name); err != nil {
						return res, utils.WrapError(err, "OutLetOpen: 13，redis保存设备价格失败")
					}
				}
			} else {
				if qldOutletControl, err2 := models.GetQldOutletControlById(qldOutlets[0].ControlId); err2 != nil {
					return res, utils.WrapError(err2, "OutLetOpen: 11，获取设备价格失败")
				} else {
					if err = service.RedisSave(p.SnNum+"/control", qldOutletControl.ControlStr); err != nil {
						return res, utils.WrapError(err, "OutLetOpen: 13，redis保存设备价格失败")
					}
				}
			}

			res.TimeOut, res.OpenFlag, err = service.OperateDevice(p.SnNum, service.OperateDeviceOpenIOValue, p.OpenType, 2, 15)
			if err != nil {
				return res, utils.WrapError(err, "OutLetOpen: 2，控制设备失败8")
			}
			if !service.CheckState8(p.SnNum, qldOutlets[0].Type) {
				_, _, err = service.OperateDevice(p.SnNum, service.OperateDeviceCloseIOValue, p.OpenType, 2, 15)
				res.OpenFlag = 2
				res.OpenMsg = "汽车未允许充电,请检查汽车和充电枪"
				return res, nil
			}
			if res.OpenFlag != 0 {
				if qldOutlets[0].Type == 4 && (res.OpenFlag == 4 || res.OpenFlag == 3) {
					res.OpenMsg = "请先连接电池"
				}
				//设置错误信息_start
				//if cmdResponse == "0" { //正常充电
				//	return false, 0, nil
				//} else if cmdResponse == "1" || cmdResponse == "h" { //电流过大
				//	return false, 21, nil
				//} else if cmdResponse == "2" || cmdResponse == "3" { //未连接电池
				//	return false, 22, nil
				//} else if cmdResponse == "c" || cmdResponse == "8" { //充满停止
				//	return false, 8, nil
				//} else if cmdResponse == "9" { //充电器及电池存在漏电风险
				//	return false, 24, nil
				//} else if cmdResponse == "a" { //充电器及电池存在短路风险
				//	return false, 25, nil
				//} else if cmdResponse == "b" { //充电器反馈异常
				//	return false, 26, nil
				//} else if cmdResponse == "d" { //设备拔出停止
				//	return false, 27, nil
				//} else if cmdResponse == "f" { //电网电压异常
				//	return false, 28, nil
				//} else if cmdResponse == "7" { //充电电流过小停止
				//	return false, 29, nil
				//} else if cmdResponse == "x" { //异常停止
				//	return false, 30, nil
				//}  else if cmdResponse == "off-line" || cmdResponse == "y" { //设备离线
				//	return false, 11, nil
				//}
				if res.OpenFlag == 21 {
					res.OpenMsg = "电流过大"
				} else if res.OpenFlag == 22 {
					res.OpenMsg = "未连接电池"
				} else if res.OpenFlag == 8 {
					res.OpenMsg = "充满停止"
				} else if res.OpenFlag == 24 {
					res.OpenMsg = "充电器及电池存在漏电风险"
				} else if res.OpenFlag == 25 {
					res.OpenMsg = "充电器及电池存在短路风险"
				} else if res.OpenFlag == 26 {
					res.OpenMsg = "充电器反馈异常"
				} else if res.OpenFlag == 27 {
					res.OpenMsg = "设备拔出停止"
				} else if res.OpenFlag == 28 {
					res.OpenMsg = "电网电压异常"
				} else if res.OpenFlag == 29 {
					res.OpenMsg = "充电电流过小停止"
				} else if res.OpenFlag == 30 {
					res.OpenMsg = "异常停止"
				} else if res.OpenFlag == 11 {
					res.OpenMsg = "设备离线"
				}

				//设置错误信息_end
				utils.MyPrint(utils.PRINT_INFO, p.SnNum, "打开标志错误", res.OpenFlag)
			} else if !res.TimeOut {
				err2 := models.SetQldOutletValue(p.SnNum, 1, p.UserID)
				if err2 != nil {
					return res, utils.WrapError(err2, "OutLetOpen: 6，更新数据库失败")
				}
				if err = service.SaveOpenTime(p.SnNum); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 3，保存打开时间失败")
				}
				if err = service.SaveOpenType(p.SnNum, p.OpenType); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 4，保存打开类型失败")
				}
				if err = service.RedisSave(p.SnNum+"/batteryType", strconv.FormatInt(p.BatteryType, 10)); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 13，redis保存设备价格失败")
				}
				if err = service.RedisSaveNoHeader("userBalance/"+strconv.FormatInt(p.UserID, 10), strconv.FormatInt(p.Balance, 10)); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 5，保存用户余额失败")
				}
				if err = service.RedisSave(p.SnNum+"/openAmount", strconv.FormatInt(p.Amount, 10)); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 7，isWorking保存到redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/orderSn", p.OrderSn); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 8，orderSn保存到redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/userId", strconv.FormatInt(p.UserID, 10)); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 9，userId保存到redis失败")
				}
				if err = service.SaveUserIdAndSnNum(p.UserID, p.SnNum); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 10，userId_snNum保存到redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/electricityOpen", "electricityOpen"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityOpen清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/electricityLast", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/electricity", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricity清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/electricity", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 15，current清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/amount", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 16，amount清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/remainAmount", strconv.FormatInt(p.Balance, 10)); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 17，remainAmount清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/remainAmount", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/soc", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "OutLetOpen: 18，soc清零redis失败"))
				}
				if err = service.MqttNoticeSend(p.SnNum+"/soc", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/dSoc", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "OutLetOpen: 19，dSoc清零redis失败"))
				}
				if err = service.MqttNoticeSend(p.SnNum+"/dSoc", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/timeLeft", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "OutLetClose: 20，timeLeft清零redis失败"))
				}
				if err = service.MqttNoticeSend(p.SnNum+"/timeLeft", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/amountRecord", ""); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 18，amountRecord保存到redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/timeType", strconv.FormatInt(p.TimeType, 10)); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 19，timeType保存到redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/hourNum", strconv.FormatInt(p.Hour, 10)); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 20，hourNum保存到redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/isWorking", "1"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 7，isWorking保存到redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/isWorking", "1"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: isWorking推送失败")
				}
				if err = service.RedisSave(p.SnNum+"/stepelec", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "stepelec 清理失败"))
				}
			} else {
				utils.MyPrint(utils.PRINT_INFO, p.SnNum, "打开超时")
			}
		}
	}
	//fmt.Println("最后:", res)
	return res, nil
}

// CardOutLetOpen 打开设备
func (that *handlerDevController) OutLetChangeOpen(ctx context.Context, p *dev.OutLetChangeOpenRequest) (res *dev.OutLetChangeOpenResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetChangeOpen request", utils.TransProtoToJson(p))
	defer func() {
		if err != nil {
			service.PutErrorMsg("OutLetChangeOpen"+err.Error(), p.SnNum, service.UserControlErr)
			res.OpenResult = 1
			res.OpenMsg = "操作错误"
			utils.MyPrint(utils.PRINT_ERROR, err.Error())
		}
		utils.MyPrint(utils.PRINT_INFO, "OutLetChangeOpen response", utils.TransProtoToJson(res))
	}()
	res = &dev.OutLetChangeOpenResponse{}
	res.OpenResult = service.CheckOpenType(p.SnNum, p.OpenType)
	if res.OpenResult != 0 {
		return res, nil
	}
	if res.TimeOut, _, err = service.OperateDevice(p.SnNum, service.OperateDeviceChangeIOValue, p.OpenType, 2, 15); err != nil {
		return res, utils.WrapError(err, "OutLetChangeOpen: 1，控制设备失败7")
	}
	if !res.TimeOut {
		if err = service.SaveOpenType(p.SnNum, p.OpenType); err != nil {
			return res, utils.WrapError(err, "OutLetChangeOpen: 3，保存打开类型失败")
		}
	} else {
		utils.MyPrint(utils.PRINT_INFO, p.SnNum, "修改超时")
	}
	return res, nil
}

// OutLetClose 关闭设备
func (that *handlerDevController) OutLetClose(ctx context.Context, p *dev.OutLetCloseRequest) (res *dev.OutLetCloseResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetClose request", utils.TransProtoToJson(p))
	res = &dev.OutLetCloseResponse{}
	if err = service.RedisSave(p.SnNum+"/operateFlag", ""); err != nil {
		return res, utils.WrapError(err, "OutLetClose: redis保存operateFlag失败")
	}
	defer func() {
		if res.CloseFlag == 0 && !res.TimeOut { //成功结束，推送orderSn
			orderSn := res.OrderSn
			time.AfterFunc(5*time.Second, func() {
				b, err2 := json.Marshal(map[string]interface{}{
					"orderSn": orderSn,
					"retCode": 200,
				})
				if err2 != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err2, "OutLetClose:json字符串转换获取失败"))
				}
				if err = service.MqttNoticeSend(p.SnNum+"/orderFinish", string(b)); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "OutLetClose:orderFinish信息推送失败"))
				}
			})
		}
		if err2 := service.RedisDel(p.SnNum + "/operateFlag"); err2 != nil {
			utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err2, "OutLetClose: redis删除operateFlag失败"))
		}
		if err != nil {
			service.PutErrorMsg("OutLetClose"+err.Error(), p.SnNum, service.UserControlErr)
			utils.MyPrint(utils.PRINT_ERROR, err.Error())
			err = nil
			res.CloseFlag = 1
			res.CloseMsg = "操作错误"
		}
		utils.MyPrint(utils.PRINT_INFO, "OutLetClose response", utils.TransProtoToJson(res))
	}()

	if qldOutlets, err2 := models.GetQldOutletsBySnNum(p.SnNum); err2 != nil {
		return res, utils.WrapError(err2, "OutLetClose: 1，获取数据设备信息失败")
	} else if len(qldOutlets) == 0 {
		return res, nil
	} else {
		if qldOutlets[0].Type == 6 || qldOutlets[0].Type == 10 || qldOutlets[0].Type == 12 || qldOutlets[0].Type == 13 {
			res.TimeOut, res.CloseFlag, res.Amount, res.Electricity, res.Duration, res.OrderSn, res.AmountRecord, res.CloseMsg, err = service.DeviceClose(p.UserID, p.SnNum)
		} else if qldOutlets[0].Type == 8 {
			res.TimeOut, res.CloseFlag, res.Amount, res.Electricity, res.Duration, res.OrderSn, res.AmountRecord, res.CloseMsg, err = service.StopChargingSpw(p.UserID, p.SnNum)
		} else {
			res.TimeOut, res.CloseFlag, err = service.OperateDevice(p.SnNum, service.OperateDeviceCloseIOValue, 0, 2, 15)
			if err != nil {
				return res, utils.WrapError(err, "OutLetClose:2，控制设备失败6")
			}
			if res.CloseFlag != 0 {
				return res, nil
			} else if !res.TimeOut {
				if err2 := models.SetQldOutletValue(p.SnNum, 0, 0); err2 != nil {
					return res, utils.WrapError(err2, "OutLetClose关闭设备:3，更新数据库失败")
				}
				if res.Duration, err = service.AnalyzeDevDurationGet(p.SnNum + "/openTime"); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备:7，获取订单时间失败")
				}

				if electricity, err2 := service.AnalyzeDevPowerElectricityGet(p.SnNum); err2 != nil {
					return res, utils.WrapError(err2, "OutLetClose关闭设备:9，获取订单电量失败")
				} else {

					utils.MyPrint(utils.PRINT_INFO, p.SnNum, "获取的电量", electricity, "设备类型:", qldOutlets[0].Type)
					//判断电量异常_start
					if qldOutlets[0].Type == 5 || qldOutlets[0].Type == 9 {
						socketScooterThreshold := 10.0
						if qldOutlets[0].Type == 5 {
							socketThresholdRedis, err := service.RedisGetNoHeader("/socket/threshold", "10")
							if err == nil {
								socketFloatValue, err := strconv.ParseFloat(socketThresholdRedis, 64)
								if err == nil {
									socketScooterThreshold = socketFloatValue
								}

							}
						}

						if qldOutlets[0].Type == 9 {
							scooterThresholdRedis, err := service.RedisGetNoHeader("/scooter/threshold", "50")
							if err == nil {
								scooterFloatValue, err := strconv.ParseFloat(scooterThresholdRedis, 64)
								if err == nil {
									socketScooterThreshold = scooterFloatValue
								}

							}
						}
						utils.MyPrint(utils.PRINT_INFO, p.SnNum, "获取的电量判断阈值:", socketScooterThreshold, "设备类型:", qldOutlets[0].Type)

						if electricity > socketScooterThreshold {
							utils.MyPrint(utils.PRINT_ERROR, p.SnNum, "电量错误")
							electricity = 0.5
							_ = service.RedisSave(p.SnNum+"/electricity", strconv.FormatFloat(electricity, 'E', -1, 64))
						}

					}

					//判断电量异常_end

					res.Electricity = float32(electricity)
				}
				if res.OrderSn, err = service.SpecialOrderSnGet(p.SnNum+"/orderSn", ""); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备:10，活动订单sn失败")
				}

				//if res.Amount, err = service.AnalyzeDevPowerAmountGet(p.SnNum); err != nil {
				//	return res, utils.WrapError(err, "OutLetClose关闭设备:8，获取订单金额失败")
				//}
				//timetype, err := service.RedisGet(p.SnNum+"/timeType", "0")
				//if timetype == "2" {
				//	if res.AmountRecord, err = service.RedisGet(p.SnNum+"/amountRecord", "0"); err != nil {
				//		return res, utils.WrapError(err, "OutLetClose关闭设备:10，活动订单sn失败")
				//	}
				//
				//} else {
				//	if res.AmountRecord, err = service.CalculateAmountRecord(p.SnNum); err != nil {
				//		return res, utils.WrapError(err, "OutLetClose关闭设备:10，活动订单sn失败")
				//	}
				//}

				if res.Amount, res.AmountRecord, err = service.CalculateAmountType(p.SnNum); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备:8，获取订单金额失败")
				}

				if err = service.RedisDel(p.SnNum + "/userId"); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备: 5，redis删除userId失败")
				}
				if err = service.DelUserIdAndSnNum(p.UserID, p.SnNum); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备: 6，redis删除userId_snNum失败")
				}
				if err = service.RedisSave(p.SnNum+"/electricity", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 12，electricity清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/electricity", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/power", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 13，power清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/power", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				//if err = service.RedisSave(p.SnNum+"/maxPower", "0"); err != nil {
				//	return res, utils.WrapError(err, "OutLetClose: 13，power清零redis失败")
				//}
				if err = service.RedisSave(p.SnNum+"/voltage", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，voltage清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/voltage", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 15，current清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/amount", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 16，amount清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/amount", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/remainAmount", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 17，remainAmount清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/remainAmount", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/soc", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 18，soc清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/soc", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/dSoc", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 19，dSoc清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/dSoc", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/timeLeft", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 20，timeLeft清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/timeType", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: timeType清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/timeLeft", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/isWorking", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 4，isWorking保存到redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/isWorking", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: isWorking推送失败")
				}

				//adddd

				// add new
				if err = service.RedisSave(p.SnNum+"/restart", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "restart 清理失败"))
				}
				if err = service.RedisSave(p.SnNum+"/stoptime", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "stoptime 清理失败"))
				}
				if err = service.RedisSave(p.SnNum+"/stepelec", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "stepelec 清理失败"))
				}
				if err = service.RedisSave(p.SnNum+"/duration", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "stepelec 清理失败"))
				}
			} else {
				utils.MyPrint(utils.PRINT_INFO, p.SnNum, "关闭超时")
			}
		}
	}
	return res, nil
}

// OutLetCmd 设备命令
func (that *handlerDevController) OutLetCmd(ctx context.Context, p *dev.OutLetCmdRequest) (res *dev.OutLetCmdResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetCmd request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "OutLetCmd response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("OutLetCmd"+err.Error(), p.CmdSendTopic, service.UserControlErr)
		}
	}()
	res = &dev.OutLetCmdResponse{}
	if res.CmdResponse, res.TimeOut, err = service.MqttCmdDevice(p.CmdSendTopic, p.CmdRecvTopic, p.CmdStr, 1, 10); err != nil {
		return res, utils.WrapError(err, "设备命令，控制设备失败5")
	}
	return res, nil
}

// OutLetMakeListenTopic 设备命令
func (that *handlerDevController) OutLetMakeMqttListenTopic(ctx context.Context, p *dev.OutLetMakeMqttListenTopicRequest) (res *dev.OutLetMakeMqttListenTopicResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetMakeMqttListenTopic request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "OutLetMakeMqttListenTopic response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("OutLetMakeMqttListenTopic"+err.Error(), "", service.UserControlErr)
		}
	}()
	res = &dev.OutLetMakeMqttListenTopicResponse{}
	//res.Topic = service.MakeMqttListenDeviceTopic()
	return res, nil
}

// OutLetAnalyzeMqttData 设备命令
func (that *handlerDevController) OutLetAnalyzeMqttMessage(ctx context.Context, p *dev.OutLetAnalyzeMqttMessageRequest) (res *dev.OutLetAnalyzeMqttMessageResponse, err error) {
	//utils.MyPrint(utils.PRINT_INFO , "OutLetAnalyzeMqttMessage request", utils.TransProtoToJson(p))
	//defer func() {
	//	utils.MyPrint(utils.PRINT_INFO , "OutLetAnalyzeMqttMessage response",res,err.Error())
	//}()
	res = &dev.OutLetAnalyzeMqttMessageResponse{}
	service.AnalyzeMqttListrnMessageResponse(p.Topic, p.Message)
	return res, nil
}

// OutLetMakeListenTopic 设备命令
func (that *handlerDevController) OutLetMakeEtcdListenKey(ctx context.Context, p *dev.OutLetMakeEtcdListenKeyRequest) (res *dev.OutLetMakeEtcdListenKeyResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetMakeEtcdListenKey request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "OutLetMakeEtcdListenKey response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("OutLetMakeEtcdListenKey"+err.Error(), p.SnNum, service.UserControlErr)
		}
	}()
	res = &dev.OutLetMakeEtcdListenKeyResponse{}

	res.Key = service.MakeEtcdListenKey(p.SnNum)

	return res, nil
}

// OutLetMakeDevOnlineEtcdListenKey 设备命令
func (that *handlerDevController) OutLetMakeDevOnlineEtcdListenKey(ctx context.Context, p *dev.OutLetMakeDevOnlineEtcdListenKeyRequest) (res *dev.OutLetMakeDevOnlineEtcdListenKeyResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetMakeDevOnlineEtcdListenKey request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "OutLetMakeDevOnlineEtcdListenKey response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("OutLetMakeDevOnlineEtcdListenKey"+err.Error(), p.SnNum, service.UserControlErr)
		}
	}()
	res = &dev.OutLetMakeDevOnlineEtcdListenKeyResponse{}
	res.Key, err = service.MakeDevOnlineEtcdListenKey(p.SnNum)
	return
}

// OutLetMakeDevOnlineEtcdListenKey 设备命令
func (that *handlerDevController) OutLetDevOnlineEtcdCheck(ctx context.Context, p *dev.OutLetDevOnlineEtcdCheckRequest) (res *dev.OutLetDevOnlineEtcdCheckResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetDevOnlineEtcdCheck request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "OutLetDevOnlineEtcdCheck response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("OutLetDevOnlineEtcdCheck"+err.Error(), p.SnNum, service.UserControlErr)
		}
	}()
	res = &dev.OutLetDevOnlineEtcdCheckResponse{}
	res.Online, err = service.DevOnlineEtcdCheck(p.SnNum)
	return
}

// OutLetElectricityGet 获取设备电量
func (that *handlerDevController) OutLetElectricityGet(ctx context.Context, p *dev.OutLetElectricityGetRequest) (res *dev.OutLetElectricityGetResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetElectricityGet request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "OutLetElectricityGet response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("OutLetElectricityGet"+err.Error(), p.SnNum, service.UserControlErr)
		}
	}()
	res = &dev.OutLetElectricityGetResponse{}
	electricity, _ := service.AnalyzeDevPowerElectricityGet(p.SnNum)
	res.Electricity = float32(electricity)
	return
}

// OutLetAmountGet 获取设备电费
func (that *handlerDevController) OutLetAmountGet(ctx context.Context, p *dev.OutLetAmountGetRequest) (res *dev.OutLetAmountGetResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "OutLetAmountGet request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "OutLetAmountGet response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("OutLetAmountGet"+err.Error(), p.SnNum, service.UserControlErr)
		}
	}()
	res = &dev.OutLetAmountGetResponse{}
	res.Amount, err = service.AnalyzeDevPowerAmountGet(p.SnNum)
	return
}

// GetQldOutletTypeBySnNum 获取设备类型
func (that *handlerDevController) GetQldOutletTypeBySnNum(ctx context.Context, p *dev.GetQldOutletTypeBySnNumRequest) (res *dev.GetQldOutletTypeBySnNumResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "GetQldOutletTypeBySnNum request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "GetQldOutletTypeBySnNum response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("GetQldOutletTypeBySnNum"+err.Error(), p.SnNum, service.UserControlErr)
		}
	}()
	res = &dev.GetQldOutletTypeBySnNumResponse{}
	utils.MyPrint(utils.PRINT_INFO, p.SnNum, p.UserId)
	res.QldOutletType, res.OperateFlag, res.OpenType, res.OpenDuration, res.Status, res.PriceDes, res.ErrMsg, err = service.GetQldOutletTypeBySnNum(p.SnNum, p.UserId)
	return
}

// GetQldOutletChargeInfo 重新获取设备充电信息
func (that *handlerDevController) GetQldOutletChargeInfo(ctx context.Context, p *dev.GetQldOutletChargeInfoRequest) (res *dev.GetQldOutletChargeInfoResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "GetQldOutletChargeInfo request", utils.TransProtoToJson(p))
	defer func() {
		utils.MyPrint(utils.PRINT_INFO, "GetQldOutletChargeInfo response", utils.TransProtoToJson(res))
		if err != nil {
			service.PutErrorMsg("GetQldOutletChargeInfo"+err.Error(), p.SnNum, service.UserControlErr)
		}
	}()
	res = &dev.GetQldOutletChargeInfoResponse{}

	if len(p.SnNum) == 0 {
		return
	}
	//redisKeys, err2 := service.RedisKeyList(p.SnNum)
	//if err2 != nil {
	//	err = utils.WrapError(err2, "GetQldOutletChargeInfo:获取redis的key list失败")
	//	if err != nil {
	//		utils.MyPrint(utils.PRINT_ERROR, err.Error())
	//	}
	//	return
	//}
	redisKeys := make([]string, 0)
	voltage := "/qld2devservice/" + p.SnNum + "/voltage"
	current := "/qld2devservice/" + p.SnNum + "/current"
	power := "/qld2devservice/" + p.SnNum + "/power"
	connectInfo := "/qld2devservice/" + p.SnNum + "/connectInfo"
	remainAmount := "/qld2devservice/" + p.SnNum + "/remainAmount"

	redisKeys = append(redisKeys, voltage, current, power, connectInfo, remainAmount)
	//fmt.Println("redisKeys:", redisKeys)
	for m := 0; m < len(redisKeys); m++ {
		if result, err2 := service.RedisGetNoHeader(redisKeys[m], ""); err2 != nil {
			err = utils.WrapError(err2, "GetQldOutletChargeInfo:读取redis数据失败")
			if err != nil {
				utils.MyPrint(utils.PRINT_ERROR, err.Error())
			}
			return
		} else {
			if err = service.MqttNoticeSendNoHeader(redisKeys[m], result); err != nil {
				return res, utils.WrapError(err, "GetQldOutletChargeInfo: MqttNoticeSend发送数据失败")
			}
		}
	}
	//etcdKeys, err2 := service.EtcdDataKeyListGet(p.SnNum)
	//if err2 != nil {
	//	err = utils.WrapError(err2, "GetQldOutletChargeInfo:获取etcd的key list失败")
	//	utils.MyPrint(utils.PRINT_ERROR , err.Error())
	//}
	//for m := 0; m < len(etcdKeys); m++ {
	//	if result, err2 := service.EtcdDataGetNoHead(etcdKeys[m], ""); err2 != nil {
	//		err = utils.WrapError(err2, "GetQldOutletChargeInfo:读取redis数据失败")
	//		utils.MyPrint(utils.PRINT_ERROR , err.Error())
	//		return
	//	} else {
	//		if err = service.MqttNoticeSendNoHeader(etcdKeys[m], result); err != nil {
	//			return res, utils.WrapError(err, "GetQldOutletChargeInfo: MqttNoticeSend发送数据失败")
	//		}
	//		if err = service.EtcdDataSaveNoHead(etcdKeys[m], result); err != nil {
	//			return res, utils.WrapError(err, "GetQldOutletChargeInfo: EtcdDataSaveNoHead发送数据失败")
	//		}
	//	}
	//}
	return
}

// CardOutLetOpen 用卡打开设备
func (that *handlerDevController) CardOutLetOpen(ctx context.Context, p *dev.CardOutLetOpenRequest) (res *dev.CardOutLetOpenResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "CardOutLetOpen request", utils.TransProtoToJson(p))
	if err = service.RedisSave(p.SnNum+"/operateFlag", ""); err != nil {
		return res, utils.WrapError(err, "CardOutLetOpen: redis保存operateFlag失败")
	}
	defer func() {
		if res.OpenFlag > 0 || res.TimeOut {
			if err1 := models.SetQldOutletValue(p.SnNum, 0, 0); err1 != nil {
				utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err1, "CardOutLetOpen: 0，更新数据库失败"))
			}
		} else {
			orderSn := p.OrderSn
			time.AfterFunc(5*time.Second, func() {
				b, err2 := json.Marshal(map[string]interface{}{
					"orderSn": orderSn,
					"retCode": 200,
				})
				if err2 != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err2, "OutLetOpen:json字符串转换获取失败"))
				}
				if err2 = service.MqttNoticeSend(p.SnNum+"/orderCreate", string(b)); err2 != nil {
					utils.MyPrint(utils.PRINT_ERROR, err2.Error())
				}
			})
		}
		if err2 := service.RedisDel(p.SnNum + "/operateFlag"); err2 != nil {
			utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err2, "CardOutLetOpen: redis删除operateFlag失败"))
		}
		if err != nil {
			service.PutErrorMsg("CardOutLetOpen"+err.Error(), p.SnNum, service.UserControlErr)
			res.OpenFlag = 1
			res.OpenMsg = "操作错误"
			utils.MyPrint(utils.PRINT_ERROR, err.Error())
		}
		utils.MyPrint(utils.PRINT_INFO, "CardOutLetOpen response", utils.TransProtoToJson(res))
		err = nil
	}()
	res = &dev.CardOutLetOpenResponse{}

	if qldOutlets, err2 := models.GetQldOutletsBySnNum(p.SnNum); err2 != nil {
		return res, utils.WrapError(err2, "CardOutLetOpen: 1，获取数据设备信息失败")
	} else if len(qldOutlets) == 0 {
		return res, nil
	} else {
		if qldOutlets[0].Type == 6 {
			//后面的两个参数在这里用不到,传1
			res.TimeOut, res.OpenFlag, res.OpenMsg, err = service.DeviceOpen(p.UserID, p.SnNum, p.OrderSn, p.Amount, p.Balance, p.OpenType, 1, 1)
		} else {
			res.TimeOut, res.OpenFlag, err = service.OperateDevice(p.SnNum, service.OperateDeviceOpenIOValue, p.OpenType, 2, 15)
			if err != nil {
				return res, utils.WrapError(err, "CardOutLetOpen: 2，控制设备失败4")
			}
			if res.OpenFlag != 0 {
				return res, nil
			} else if !res.TimeOut {
				if err = service.RedisSave(p.SnNum+"/openByCard", "openByCard"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "CardOutLetOpen: 0，opening设置redis失败"))
				}
				err2 := models.SetQldOutletValue(p.SnNum, 1, p.UserID)
				if err2 != nil {
					return res, utils.WrapError(err2, "CardOutLetOpen: 6，更新数据库失败")
				}
				if err = service.SaveOpenTime(p.SnNum); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 3，保存打开时间失败")
				}
				if err = service.SaveOpenType(p.SnNum, p.OpenType); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 4，保存打开类型失败")
				}
				if err = service.RedisSave(p.SnNum+"/batteryType", strconv.FormatInt(p.BatteryType, 10)); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 13，redis保存设备价格失败")
				}
				if err = service.RedisSaveNoHeader("userBalance/"+strconv.FormatInt(p.UserID, 10), strconv.FormatInt(p.Balance, 10)); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 5，保存用户余额失败")
				}
				if err = service.RedisSave(p.SnNum+"/openAmount", strconv.FormatInt(p.Amount, 10)); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 7，isWorking保存到redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/orderSn", p.OrderSn); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 8，orderSn保存到redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/userId", strconv.FormatInt(p.UserID, 10)); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 9，userId保存到redis失败")
				}
				if err = service.SaveUserIdAndSnNum(p.UserID, p.SnNum); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 10，userId_snNum保存到redis失败")
				}
				if qldAmountPrice, err2 := models.GetQldAmountPriceById(qldOutlets[0].PriceId); err2 != nil {
					return res, utils.WrapError(err2, "CardOutLetOpen: 11，获取设备价格失败")
				} else {
					if err = service.RedisSave(p.SnNum+"/price", qldAmountPrice.PriceStr); err != nil {
						return res, utils.WrapError(err, "CardOutLetOpen: 13，redis保存设备价格失败")
					}
				}
				if qldOutletControl, err2 := models.GetQldOutletControlById(qldOutlets[0].ControlId); err2 != nil {
					return res, utils.WrapError(err2, "CardOutLetOpen: 11，获取设备价格失败")
				} else {
					if err = service.RedisSave(p.SnNum+"/control", qldOutletControl.ControlStr); err != nil {
						return res, utils.WrapError(err, "CardOutLetOpen: 13，redis保存设备价格失败")
					}
				}
				if err = service.RedisSave(p.SnNum+"/electricityOpen", "electricityOpen"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityOpen清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/electricityLast", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/electricity", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricity清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/electricity", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 15，current清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/amount", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 16，amount清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/amount", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/remainAmount", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 17，remainAmount清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/remainAmount", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/soc", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "CardOutLetOpen: 18，soc清零redis失败"))
				}
				if err = service.MqttNoticeSend(p.SnNum+"/soc", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/dSoc", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "CardOutLetOpen: 19，dSoc清零redis失败"))
				}
				if err = service.MqttNoticeSend(p.SnNum+"/dSoc", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/timeLeft", "0"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "CardOutLetOpen: 20，timeLeft清零redis失败"))
				}
				if err = service.MqttNoticeSend(p.SnNum+"/timeLeft", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/isWorking", "1"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 7，isWorking保存到redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/isWorking", "1"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: isWorking推送失败")
				}
			} else {
				utils.MyPrint(utils.PRINT_INFO, p.SnNum, "打开超时")
			}
		}
	}
	return res, nil
}

// CardOutLetClose 用卡关闭设备
func (that *handlerDevController) CardOutLetClose(ctx context.Context, p *dev.CardOutLetCloseRequest) (res *dev.CardOutLetCloseResponse, err error) {
	utils.MyPrint(utils.PRINT_INFO, "CardOutLetClose request", utils.TransProtoToJson(p))
	if err = service.RedisSave(p.SnNum+"/operateFlag", ""); err != nil {
		return res, utils.WrapError(err, "CardOutLetClose: redis保存operateFlag失败")
	}
	res = &dev.CardOutLetCloseResponse{}
	defer func() {
		if res.CloseFlag == 0 && !res.TimeOut {
			orderSn := res.OrderSn
			time.AfterFunc(5*time.Second, func() {
				b, err2 := json.Marshal(map[string]interface{}{
					"orderSn": orderSn,
					"retCode": 200,
				})
				if err2 != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err2, "OutLetClose:json字符串转换获取失败"))
				}
				if err = service.MqttNoticeSend(p.SnNum+"/orderFinish", string(b)); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "OutLetClose:orderFinish信息推送失败"))
				}
			})
		}
		if err2 := service.RedisDel(p.SnNum + "/operateFlag"); err2 != nil {
			utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err2, "CardOutLetClose: redis删除operateFlag失败"))
		}
		if err != nil {
			service.PutErrorMsg("CardOutLetClose"+err.Error(), p.SnNum, service.UserControlErr)
			res.CloseFlag = 1
			res.CloseMsg = "操作错误"
			utils.MyPrint(utils.PRINT_ERROR, err.Error())
		}
		utils.MyPrint(utils.PRINT_INFO, "CardOutLetClose response", utils.TransProtoToJson(res))
	}()

	if qldOutlets, err2 := models.GetQldOutletsBySnNum(p.SnNum); err2 != nil {
		return res, utils.WrapError(err2, "OutLetClose: 1，获取数据设备信息失败")
	} else if len(qldOutlets) == 0 {
		return res, nil
	} else {
		if qldOutlets[0].Type == 6 {
			res.TimeOut, res.CloseFlag, res.Amount, res.Electricity, res.Duration, res.OrderSn, res.AmountRecord, res.CloseMsg, err = service.DeviceClose(p.UserID, p.SnNum)
		} else {
			res.TimeOut, res.CloseFlag, err = service.OperateDevice(p.SnNum, service.OperateDeviceCloseIOValue, 0, 2, 15)
			if err != nil {
				return res, utils.WrapError(err, "OutLetClose:2，控制设备失败3")
			}
			if res.CloseFlag != 0 {
				return res, nil
			} else if !res.TimeOut {
				if err2 := models.SetQldOutletValue(p.SnNum, 0, 0); err2 != nil {
					return res, utils.WrapError(err2, "OutLetClose关闭设备:3，更新数据库失败")
				}
				if res.Duration, err = service.AnalyzeDevDurationGet(p.SnNum + "/openTime"); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备:7，获取订单时间失败")
				}
				//if res.Amount, err = service.AnalyzeDevPowerAmountGet(p.SnNum); err != nil {
				//	return res, utils.WrapError(err, "OutLetClose关闭设备:8，获取订单金额失败")
				//}

				if res.Amount, res.AmountRecord, err = service.CalculateAmountType(p.SnNum); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备:8，获取订单金额失败")
				}

				if electricity, err2 := service.AnalyzeDevPowerElectricityGet(p.SnNum); err2 != nil {
					return res, utils.WrapError(err2, "OutLetClose关闭设备:9，获取订单电量失败")
				} else {
					res.Electricity = float32(electricity)
				}
				if res.OrderSn, err = service.SpecialOrderSnGet(p.SnNum+"/orderSn", ""); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备:10，活动订单sn失败")
				}
				//if res.AmountRecord, err = service.CalculateAmountRecord(p.SnNum); err != nil {
				//	return res, utils.WrapError(err, "OutLetClose关闭设备:10，活动订单sn失败")
				//}
				if err = service.RedisSave(p.SnNum+"/isWorking", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: 4，isWorking保存到redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/isWorking", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetOpen: isWorking推送失败")
				}
				if err = service.RedisDel(p.SnNum + "/userId"); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备: 5，redis删除userId失败")
				}
				if err = service.DelUserIdAndSnNum(p.UserID, p.SnNum); err != nil {
					return res, utils.WrapError(err, "OutLetClose关闭设备: 6，redis删除userId_snNum失败")
				}
				if err = service.RedisSave(p.SnNum+"/electricity", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 12，electricity清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/electricity", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/power", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 13，power清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/power", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/voltage", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 14，voltage清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/voltage", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 15，current清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/current", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/amount", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 16，amount清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/amount", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/remainAmount", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 17，remainAmount清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/remainAmount", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/soc", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 18，soc清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/soc", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/dSoc", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 19，dSoc清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/dSoc", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisSave(p.SnNum+"/timeLeft", "0"); err != nil {
					return res, utils.WrapError(err, "OutLetClose: 20，timeLeft清零redis失败")
				}
				if err = service.MqttNoticeSend(p.SnNum+"/timeLeft", "0"); err != nil {
					return res, utils.WrapError(err, "CardOutLetOpen: 14，electricityLast清零redis失败")
				}
				if err = service.RedisDel(p.SnNum + "/openByCard"); err != nil {
					utils.MyPrint(utils.PRINT_ERROR, utils.WrapError(err, "CardOutLetClose: 0，opening设置redis失败"))
				}
			} else {
				utils.MyPrint(utils.PRINT_WARN, p.SnNum, "关闭超时")
			}
		}
	}
	return res, nil
}
